package cn.cdeden.knowledge.dubbo;

import cn.cdeden.common.core.utils.MapstructUtils;
import cn.cdeden.common.oss.enumd.OssModuleOperate;
import cn.cdeden.common.oss.enumd.OssModuleType;
import cn.cdeden.common.satoken.utils.LoginHelper;
import cn.cdeden.knowledge.domain.*;
import cn.cdeden.knowledge.domain.dto.*;
import cn.cdeden.knowledge.domain.enums.MessageTypeEnums;
import cn.cdeden.knowledge.enums.*;
import cn.cdeden.knowledge.service.*;
import cn.cdeden.knowledge.utils.CoreConfigUtils;
import cn.cdeden.resource.api.OssUploadService;
import cn.cdeden.resource.api.RemoteFileService;
import cn.cdeden.resource.api.RemoteOssEsService;
import cn.cdeden.resource.api.domain.*;
import cn.cdeden.system.api.RemoteConfigService;
import cn.cdeden.system.api.RemoteDifyService;
import cn.cdeden.system.api.RemoteUserService;
import cn.cdeden.system.api.model.LoginUser;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.lock.annotation.Lock4j;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ProjectName : KnowCore01
 * @Package : cn.cdeden.knowledge.dubbo
 * @ClassName : OssUploadTeamServiceImpl
 * @Author : Chengl.
 * @Description : // 团队的文件上传服务
 * @Date : 2024/12/6 16:08
 * @Version : 1.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
@DubboService(group = "team", version = "1.0.0")
public class OssUploadTeamServiceImpl implements OssUploadService {

    private final TeamFilesTreeService teamFilesTreeService;

    private final TeamRelevanceRoleService teamRelevanceRoleService;

    private final TeamService teamService;

    private final SysMessageService messageService;

    private final FilesAttentionService filesAttentionService;

    @DubboReference(check = false)
    private final RemoteUserService remoteUserService;

    @Override
    public RemoteFile getFileDataInfo(String moduleId, Long userId, JSONObject info, OssModuleOperate operate) {

        TeamFilesTree byId = teamFilesTreeService.getById(moduleId);
        Team team = teamService.getById(byId.getTeamId());
        if (operate == OssModuleOperate.upload) {
            if (!teamRelevanceRoleService.checkPermission(moduleId, String.valueOf(team.getId()), LoginHelper.getLoginUserByUserId(userId), TeamParamEnum.ADD.getParam())) {
                throw new RuntimeException("无上传权限！");
            }
        }
        if (operate == OssModuleOperate.Version_DownloadRecord) {
            if (ObjectUtils.isEmpty(byId)) {
                throw new RuntimeException("错误的 文件编码 或 不是文件或者文件夹");
            }
        } else {
            if (ObjectUtils.isEmpty(byId) || !StringUtils.equalsIgnoreCase(TreeTypeEnum.FILE.getType(), byId.getType())) {
                throw new RuntimeException("错误的 文件编码 或 不是文件");
            }
        }

        if (!teamRelevanceRoleService.checkPermission(moduleId, String.valueOf(team.getId()), remoteUserService.getUserInfo(userId), TeamParamEnum.CHECK.getParam())) {
            throw new RuntimeException("无访问权限！");
        }
        RemoteFile remoteFile = new RemoteFile();
        remoteFile.setOssId(byId.getStorageId() == null ? null : Long.valueOf(byId.getStorageId()));
        remoteFile.setVersionId(byId.getEdition());
        remoteFile.setVersionName(byId.getEditionName());
        remoteFile.setFileSize(byId.getSize());
        remoteFile.setFileSuffix(byId.getSuffix());
        remoteFile.setName(byId.getRealName());
        remoteFile.setOriginalName(byId.getRealName());
        remoteFile.setModuleType(OssModuleType.Team.getCode());
        if (teamRelevanceRoleService.checkPermission(moduleId, String.valueOf(team.getId()), remoteUserService.getUserInfo(userId), TeamParamEnum.DOWNLOAD.getParam())) {
            remoteFile.setRead(true);
            remoteFile.setEdit(true);
            remoteFile.setDownload(true);
            remoteFile.setPrint(true);
        } else if (teamRelevanceRoleService.checkPermission(moduleId, String.valueOf(team.getId()), remoteUserService.getUserInfo(userId), TeamParamEnum.UPDATE.getParam())) {
            remoteFile.setRead(true);
            remoteFile.setEdit(true);
            remoteFile.setDownload(false);
            remoteFile.setPrint(true);
        } else if (teamRelevanceRoleService.checkPermission(moduleId, String.valueOf(team.getId()), remoteUserService.getUserInfo(userId), TeamParamEnum.PRINT.getParam())) {
            remoteFile.setRead(true);
            remoteFile.setEdit(false);
            remoteFile.setDownload(false);
            remoteFile.setPrint(true);
        } else {
            remoteFile.setRead(true);
            remoteFile.setEdit(false);
            remoteFile.setDownload(false);
            remoteFile.setPrint(false);
        }

//        FilesAttentionDto attention = filesAttentionService.getAttention(moduleId, user.getUserId().toString(), TreeEnum.ENTERPRISE.getNum());
//        if (attention == null){
//            tree.setAttention("0");
//        }else {
//            tree.setAttention("1");
//        }
//        tree.setPerm(enterprisePermService.getPerms(Long.valueOf(moduleId),user.getUserId()));
//        tree.setLibraryType(TreeEnum.ENTERPRISE.getType());
//        JurisdictionResponse success = JurisdictionResponse.success(tree);
        // TODO 文件水印
//        if (byId.getWaterMarkId() != null){
//            FileWatermarkConfig watermarkConfig = fileWatermarkConfigService.getById(byId.getWaterMarkId());
//            if (watermarkConfig != null) {
//                success.setWatermarkTxt(watermarkConfig.getWatermarkTxt());
//            }
//        }
        return remoteFile;
    }

    @Override
    public RemoteOssUpload verifyData(RemoteOssUpload remoteOssUpload, Long userId) {
        //这里是对现有重名文件进行处理
        //根据parentId查询出上传的文件或者文件夹与当前路径下是否重名，如果重名生成一个新的名称
        List<TeamFilesTree> teamFilesTrees = teamFilesTreeService.nameRecheckingVerifyData(remoteOssUpload.getParentId());
        List<String> fileNameList = teamFilesTrees.stream().map(TeamFilesTree::getRealName).collect(Collectors.toList());
        if (fileNameList.contains(remoteOssUpload.getFileName())) {
            remoteOssUpload.setFileName(remoteOssUpload.getFileName() + "_" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
        }
        String parentId = remoteOssUpload.getParentId();
        TeamFilesTree parentTree = teamFilesTreeService.getById(parentId);
        Team team = teamService.getById(parentTree.getTeamId());
        //存储的路径
        remoteOssUpload.setBrandName(team.getMinioBucket());
        return remoteOssUpload;
    }

    @Override
    @Transactional
    @Lock4j(name = "team:", keys = {"#upload.parentId"}, acquireTimeout = 40000, expire = 40000)
    public RemoteFilesBucketPath upload(RemoteFilesUpload upload, Long userId) {
        String filePath = upload.getFilePath();
        if (StringUtils.isNotBlank(filePath)) {
            upload = createFolderPath(upload, userId);
        }
        String moduleId = upload.getModuleId();
        TeamFilesTree teamFilesTree;
        if (moduleId == null) {
            String parentId = upload.getParentId();
            teamFilesTree = teamFilesTreeService.getById(parentId);
        } else {
            teamFilesTree = teamFilesTreeService.getById(moduleId);
        }
        Team team = teamService.getById(teamFilesTree.getTeamId());
        createFile(remoteUserService.getUserInfo(userId), upload);
        return RemoteFilesBucketPath.of(team.getMinioBucket());
    }

    @Override
    public List<RemoteFilesDownload> downloadFile(List<String> idList, Long userId, JSONObject jsonObject) {
        List<RemoteFilesDownload> remoteFilesDownloads = teamFilesTreeService.teamDownloadFile(idList, userId);
        remoteFilesDownloads.forEach(tree -> tree.setLibraryType("team"));
        return remoteFilesDownloads;
    }

    @Lock4j(name = "team:", keys = {"#uploadDto.parentId"}, acquireTimeout = 10000, expire = 10000)
    private RemoteFilesUpload createFolderPath(RemoteFilesUpload uploadDto, Long userId) {
        String parentId = uploadDto.getParentId();
        String filePath = uploadDto.getFilePath();
        if (StringUtils.isNotBlank(filePath)) {           // 判断是否需要建立文件夹
            //创建文件夹
            Team team = teamService.getById(teamFilesTreeService.getById(parentId).getTeamId());
            Long createParentId = teamFilesTreeService.insertByPath(filePath, parentId, String.valueOf(team.getId()), String.valueOf(userId));
            uploadDto.setParentId(String.valueOf(createParentId));
            //同步到es
            teamFilesTreeService.createFileToEs(createParentId);
        }

        return uploadDto;
    }

    private void createFile(LoginUser user, RemoteFilesUpload uploadDto) {
        String remarks = uploadDto.getRemarks();
        String fileName = uploadDto.getFileName();


        JSONObject info = uploadDto.getInfo();

//        String teamId = uploadDto.getTeamId();


        String realName = uploadDto.getFileName();
        if (StringUtils.isEmpty(realName)) {
            realName = uploadDto.getFileName();
        }

        String extName = uploadDto.getFileSuffix();

        if (!uploadDto.getOperate().equals(OssModuleOperate.Edit_Save)) {

            String parentId = uploadDto.getParentId();
            TeamFilesTree parentTree = teamFilesTreeService.getById(parentId);
            Team team = teamService.getById(parentTree.getTeamId());
            Integer teamId = team.getId();

            //判断是否重复
            TeamFilesTree filesTree = teamFilesTreeService.nameRechecking(realName, String.valueOf(parentTree.getId()), extName);
            if (filesTree != null) {
                uploadDto.setFileName(uploadDto.getFileName() + "_" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
            }

            if (team.getUsedSpace() + uploadDto.getFileSize() > team.getSpace()) {
                throw new RuntimeException("可用空间不足！");
            }

            parentId = uploadDto.getParentId();

            if (!teamRelevanceRoleService.checkPermission(parentId, String.valueOf(teamId), user, TeamParamEnum.ADD.getParam())) {
                throw new RuntimeException("无上传权限！");
            }

            //创建文件
            TeamFilesTree newFileTree = teamFilesTreeService.createFile(uploadDto, parentId, fileName, remarks, null, user.getUserId().toString(), user.getUsername(), user);
            //权限继承
            teamRelevanceRoleService.extendParentPerm(parentId, String.valueOf(newFileTree.getId()));
            //同步到es
            teamFilesTreeService.createFileToEs(newFileTree.getId());

            //修改团队使用文件大小
            Team newTeam = new Team();
            newTeam.setId(teamId);
            newTeam.setUsedSpace(team.getUsedSpace() + newFileTree.getSize());
            teamService.updateById(newTeam);
        } else {
            String moduleId = uploadDto.getModuleId();
            TeamFilesTree teamFilesTree = teamFilesTreeService.getById(moduleId);
            Team team = teamService.getById(teamFilesTree.getTeamId());


            UpdateWrapper<TeamFilesTree> updateWrapper = new UpdateWrapper<>();
            updateWrapper
                .set("update_id", user.getUserId())
                .set("update_by", user.getNickname())
                .set("update_time", new Date())
                .set("edition_name", uploadDto.getVersionName())
                .set("edition", uploadDto.getVersionId())
//                .set("file_md5", uploadDto)
                .set("size", uploadDto.getFileSize())
                .eq("id", teamFilesTree.getId());
            boolean update = teamFilesTreeService.update(updateWrapper);
            teamFilesTreeService.createFileToEs(teamFilesTree.getId());

            //修改团队使用文件大小
            Team newTeam = new Team();
            newTeam.setId(team.getId());
            newTeam.setUsedSpace(team.getUsedSpace() - teamFilesTree.getSize() + uploadDto.getFileSize());
            teamService.updateById(newTeam);

            //添加消息
            List<String> attentionPeople = filesAttentionService.getAttentionPeople(String.valueOf(teamFilesTree.getId()), "1");

            for (String attentionPerson : attentionPeople) {
                //创建消息
                SysMessageDto sysMessageDto = new SysMessageDto();
                sysMessageDto.setContent("您关注的文件：“" + teamFilesTree.getRealName() + "” 进行了修改 修改人：" + user.getNickname());
                sysMessageDto.setOperator(user.getUserId().toString());
                sysMessageDto.setNodeId(teamFilesTree.getId().toString());
                sysMessageDto.setMessageType("0");
                sysMessageDto.setType(MessageTypeEnums.UPDATE.getCode());
                sysMessageDto.setFileType(MessageFileTypeEnums.TEAM.getCode());
                sysMessageDto.setRecipient(attentionPerson);
                sysMessageDto.setTeamId(String.valueOf(teamFilesTree.getTeamId()));
                messageService.addMessage(sysMessageDto);
            }
        }
    }
}

